package com.ruoyi.business.rtsp.news;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.*;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @Auther: Jacky
 * @Date: 2025-7-7 9:40
 * @Description: com.ruoyi.business.rtsp.news
 * @version: 1.0
 */
@Service
public class VideoStreamService {
    /*public ByteArrayOutputStream getVideoStream(String rtspUrl) throws Exception {
        try {
            FFmpegFrameGrabber.tryLoad();
            System.out.println("FFmpeg加载成功");
        } catch (Exception e) {
            System.err.println("FFmpeg加载失败: " + e.getMessage());
        }
        // 显式指定FFmpeg路径
        Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);

        // 或者直接加载特定库
        try {
            Loader.load(org.bytedeco.ffmpeg.global.avcodec.class);
            System.out.println("FFmpeg库加载成功");
        } catch (Exception e) {
            System.err.println("加载失败: " + e);
        }

        // 启用FFmpeg详细日志
        FFmpegLogCallback.set();

        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try {
            // 1. 配置抓取器 (显式指定HEVC解码器)
            grabber = new FFmpegFrameGrabber(rtspUrl);
            grabber.setOption("rtsp_transport", "tcp");
            grabber.setOption("stimeout", "5000000");
            grabber.setOption("fflags", "nobuffer");
            grabber.setOption("allowed_extensions", "ALL");

            // 关键配置 - 显式设置解码器
            grabber.setVideoCodecName("h264"); // 或 "h264" 根据摄像头实际编码
            grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            //grabber.setVideoCodec(avcodec.AV_CODEC_ID_H264_CUVID); // NVIDIA GPU解码

            // 2. 启动抓取器
            try {
                grabber.start();
            } catch (Exception e) {
                // 如果HEVC失败，尝试自动检测编解码器
                grabber.setVideoCodecName(null); // 重置为自动检测
                grabber.start();
            }

            // 3. 配置录制器
            recorder = new FFmpegFrameRecorder(outputStream,
                    grabber.getImageWidth(), grabber.getImageHeight(), 0);

            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFormat("flv");
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);

            // 优化参数
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("tune", "zerolatency");
            recorder.setVideoOption("crf", "23");

            // 4. 启动录制器
            recorder.start();

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                if (frame.image != null) {
                    recorder.record(frame);
                }
            }

            return outputStream;
        } finally {
            if (recorder != null) try { recorder.close(); } catch (Exception e) {}
            if (grabber != null) try { grabber.close(); } catch (Exception e) {}
        }
    }*/

    public ByteArrayOutputStream getVideoStream(String rtspUrl) throws Exception {
        try {
            FFmpegFrameGrabber.tryLoad();
            System.out.println("FFmpeg加载成功");
        } catch (Exception e) {
            System.err.println("FFmpeg加载失败: " + e.getMessage());
        }
        // 显式指定FFmpeg路径
        Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);

        // 或者直接加载特定库
        try {
            Loader.load(org.bytedeco.ffmpeg.global.avcodec.class);
            System.out.println("FFmpeg库加载成功");
        } catch (Exception e) {
            System.err.println("加载失败: " + e);
        }

        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try {
            // 1. 配置抓取器 (针对HEVC优化)
            grabber = new FFmpegFrameGrabber(rtspUrl);
            grabber.setOption("rtsp_transport", "tcp");
            grabber.setOption("stimeout", "5000000");
            grabber.setOption("fflags", "nobuffer");
            grabber.setOption("analyzeduration", "1000000");

            // 显式设置解码器为HEVC
            grabber.setVideoCodecName("h264");
            grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); // 强制输出格式

            // 禁用音频(减少复杂度)
            grabber.setAudioChannels(0);

            // 2. 启动抓取器
            grabber.start();

            // 3. 配置录制器 (H.264输出)
            recorder = new FFmpegFrameRecorder(outputStream,
                    grabber.getImageWidth(), grabber.getImageHeight(), 0);

            // 关键配置 - 使用libx264而非openh264
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFormat("flv");
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);

            // 优化转码参数
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("tune", "zerolatency");
            recorder.setVideoOption("crf", "23");
            recorder.setVideoOption("x264opts", "no-scenecut");

            // 处理颜色范围问题
            recorder.setVideoOption("color_range", "pc");
            recorder.setVideoOption("pix_fmt", "yuv420p");
            recorder.setVideoOption("sws_flags", "bilinear");

            // 设置合理的帧率和GOP
            recorder.setFrameRate(grabber.getFrameRate());
            recorder.setGopSize((int)grabber.getFrameRate());

            // 在recorder配置中添加硬件加速选项
            recorder.setVideoOption("hwaccel", "auto");
            recorder.setVideoOption("c:v", "h264_nvenc"); // NVIDIA GPU
// 或
            recorder.setVideoOption("c:v", "h264_qsv");   // Intel QuickSync

            // 4. 启动录制器
            recorder.start();

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                if (frame.image != null) {
                    try {
                        recorder.record(frame);
                    } catch (Exception e) {
                        System.err.println("Frame recording error: " + e.getMessage());
                        continue;
                    }
                }
            }

            return outputStream;
        } finally {
            // 确保资源释放
            if (recorder != null) try { recorder.stop(); } catch (Exception e) {}
            if (grabber != null) try { grabber.stop(); } catch (Exception e) {}
        }
    }

    /*public ByteArrayOutputStream getVideoStream(String rtspUrl) throws Exception {
        try {
            FFmpegFrameGrabber.tryLoad();
            System.out.println("FFmpeg加载成功");
        } catch (Exception e) {
            System.err.println("FFmpeg加载失败: " + e.getMessage());
        }
        // 显式指定FFmpeg路径
        Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);

        // 或者直接加载特定库
        try {
            Loader.load(org.bytedeco.ffmpeg.global.avcodec.class);
            System.out.println("FFmpeg库加载成功");
        } catch (Exception e) {
            System.err.println("加载失败: " + e);
        }

        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try {
            // 1. 配置抓取器
            grabber = new FFmpegFrameGrabber(rtspUrl);
            grabber.setOption("rtsp_transport", "tcp");
            grabber.setOption("stimeout", "5000000"); // 5秒超时
            grabber.setOption("fflags", "nobuffer");
            grabber.setOption("analyzeduration", "1000000"); // 减少分析时间
            grabber.setImageMode(FrameGrabber.ImageMode.RAW);

            // 2. 显式禁用音频(减少问题源)
            grabber.setAudioChannels(0);

            // 3. 启动抓取器
            grabber.start();

            // 4. 配置录制器
            recorder = new FFmpegFrameRecorder(outputStream,
                    grabber.getImageWidth(), grabber.getImageHeight(), 0); // 0音频通道

            // 关键配置 - 确保使用兼容的编解码和格式
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 强制使用H.264
            recorder.setFormat("flv");
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); // 标准格式

            // 优化参数
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("tune", "zerolatency");
            recorder.setVideoOption("crf", "23");
            recorder.setVideoOption("movflags", "faststart");

            // 处理颜色范围警告
            recorder.setVideoOption("color_range", "pc");
            recorder.setVideoOption("pix_fmt", "yuv420p");

            // 5. 启动录制器
            recorder.start();

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                // 6. 添加帧处理安全校验
                if (frame.image != null) {
                    recorder.record(frame);
                }
            }

            return outputStream;
        } finally {
            // 7. 确保按正确顺序关闭资源
            if (recorder != null) {
                try {
                    recorder.stop();
                } catch (Exception e) {
                    System.err.println("Recorder stop error: " + e.getMessage());
                }
            }
            if (grabber != null) {
                try {
                    grabber.stop();
                } catch (Exception e) {
                    System.err.println("Grabber stop error: " + e.getMessage());
                }
            }
        }
    }*/

    /*public ByteArrayOutputStream getVideoStream(String rtspUrl) throws FrameGrabber.Exception, FrameRecorder.Exception {
        FFmpegFrameRecorder recorder = null; // 在外部声明
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtspUrl);
        // 增加更多稳定性和兼容性配置
        grabber.setOption("rtsp_transport", "tcp");
        grabber.setOption("stimeout", "5000000"); // 超时设置5秒
        grabber.setOption("buffer_size", "1024000"); // 增加缓冲区
        grabber.setImageMode(FrameGrabber.ImageMode.RAW); // 使用原始图像模式
        grabber.setFrameRate(25); // 设置合理的帧率
        grabber.setVideoBitrate(1500000); // 设置比特率
        // 增加重试逻辑
        grabber.setOption("max_delay", "500000"); // 500ms
        grabber.setOption("reorder_queue_size", "0");

        try {
            grabber.start();

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            recorder = new FFmpegFrameRecorder(outputStream,
                    grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());

            // 改进的录制器配置
            recorder.setFormat("flv");
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("tune", "zerolatency");
            recorder.setVideoOption("crf", "23");
            recorder.setVideoOption("color_range", "pc"); // 明确设置颜色范围
            recorder.setVideoOption("pix_fmt", "yuv420p");
            recorder.setVideoOption("strict", "experimental");

            recorder.start();

            Frame frame;
            while ((frame = grabber.grab()) != null) {
                recorder.record(frame);
            }

            return outputStream;
        } finally {
            try {
                recorder.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                grabber.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }*/
}
